Skip to content

Add owner-authorized manual workflow triggers - #6964

Open
loganj wants to merge 11 commits into
larry/workflow-revision-foundation-v4from
larry/workflow-manual-trigger-v4
Open

Add owner-authorized manual workflow triggers#6964
loganj wants to merge 11 commits into
larry/workflow-revision-foundation-v4from
larry/workflow-manual-trigger-v4

Conversation

@loganj

@loganj loganj commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

🤖
I’m Larry.

Summary

Allow a workflow owner, or a managed agent's immutable human owner, to manually start that workflow without allowing arbitrary channel members to run another owner's automation. Signed requests identify the exact revision, and transactional authorization rechecks current membership, role, lifecycle, and revision. Ownership is not a membership bypass.

Stacked on revision foundation #6960; replaces the manual-trigger portion of #6721. Agent wakes #6965 are a separate sibling. Search/index behavior is unchanged.

Authority and retry behavior

  • Missing/stale revisions, disabled workflows, revoked authority and stale continuations are rejected. Execution/approval resumption uses the captured signed definition only while it remains current and live, rather than switching instructions or preserving superseded authority. This fences pending continuation; it does not cancel an already-running agent.
  • Separate CLI/SDK invocations receive distinct request identities. Exact signed-event replay, including after the ±15-minute admission window, recovers the original committed run acknowledgment only while the authentic event/run are retained and current exact-revision authority remains valid. Expired unseen requests are rejected, never admitted as new work. No general exactly-once side-effect guarantee, new run-lookup index, or schema uniqueness constraint is claimed.
  • Desktop now prepares/signs without publishing, then retains the complete signed trigger before submission. Outcome-ambiguous Retry resubmits that same event; concurrent/reentrant calls coalesce. Native commands use captured relay/signer snapshots so switching community/account cannot retarget an old operation.
  • The shared operation is scoped by relay, signer and workflow, survives ordinary UI remounts and community round trips, and provides pending/error/retry/success feedback on card, detail and both editor entry points. Success animation starts only after settlement. Confirmed new intent gets a new event; abandoning ambiguous work requires a warning/confirmation about possible duplicate effects.
  • Preparation failure now says execution did not start and offers ordinary retry without ambiguous-run warnings or distinct-run controls. Only attempted submission retains exact-event retry and the duplicate-effect warnings.
  • Recovery is session-only, not restart/reload-durable. A switch after submission starts need not cancel the old scoped request.
  • No migration beyond foundation 0045: nullable revision IDs, mixed-writer invalidation, NOT VALID upgrade checks; no historical validation scan or inferred legacy provenance. Schema-first rollout still takes relation locks and runtime opt-in migration has unbounded timeouts.

Exact published range and evidence

Head 4ab34922d86bc8fb11b2cab2b7447a80f5a85d30, base d2a80d819979efbf4b02e8b322a425c91c18e046 (larry/workflow-revision-foundation-v4). Previous repair 547a6ef1 is followed by P2 07e4fd21 (preparation/submission UI distinction) and P1 4ab34922 (expired committed-trigger acknowledgment). These two commits change seven files; exact reviewed head published without rebase. Author/committer and required sign-offs audited, with older history audited previously; exact lease and remote head/base verified.

Recorded local checks, reused rather than rerun during publication:

  • 16 PostgreSQL command tests passed, including five new shared production-ingest regressions using real storage, event/run transactions and executor with a counting action sink. Exact signed bytes at +901 seconds recover the original run without another effect; stale unseen/future/invalid inputs, changed authority and retention gaps reject; pending/running/waiting/failed runs are acknowledged without redispatch.
  • Restoring old timestamp ordering fails the expired exact-byte recovery regression; source was restored/hash-verified, then all 16 PG tests passed. New successful recovery also emits the existing WriteDuplicate conformance trace.
  • 1,035 relay-library tests passed / 104 ignored; relay all-target Clippy, Rustfmt and diff checks passed.
  • Four focused P2 operation/rendered Card/Detail tests passed; misclassifying preparation as submission fails both operation classification and rendered wording. TypeScript and affected Biome passed. Editor entry points consume the same scoped operation/hook/feedback; no new full editor-rendering claim.
  • Unaffected earlier 6,240 JS tests, 35 native workflow tests, 45 native relay tests / 4 ignored, native all-target Clippy, TypeScript, and affected formatting evidence retained. Native tests cover revision GET → signing → submission, committed truncated response/exact-byte retry, distinct intent and scope switching. Rebuild-on-retry mutation fails two operation tests.
  • Fixture-cache isolation regression 1 passed; test roots use owned temporary directories before AppState initialization. Historical cache loss cannot be reconstructed from Git status.
  • Earlier focused authority 14, API 3, workflow engine 169 passed / 2 ignored, plus foundation SQLx/populated and fresh-pgschema evidence remain supporting coverage.

Boundaries and known limitations

  • Expired recovery runs after signed ID/signature, content, authenticated signer and scope checks, and shares current owner/control, exact signed revision, enabled/active and owner-membership checks. It requires a retained authentic nondeleted event and a primary-store community/workflow/channel/event-bound run. A miss fails closed before persistence/spawn; ordinary fresh admission remains transactional.
  • Acknowledgment means a durable run exists, not execution completion or exactly-once execution. The pre-existing commit → spawn crash/liveness gap remains; recovery intentionally never reschedules pending/failed work. Read-only authority/retention checks are not one serializable snapshot; fresh mutation locking/rechecks are unchanged.
  • Client retry is session-memory only. Closing/reloading loses the retained operation. Changed/revoked current authority or missing retained records can prevent acknowledgment; no latest-definition fallback or repair-by-execution.
  • Native HTTP tests use a mock ledger; renderer IPC is mocked. New PG tests bind shared ingest but not a live HTTP/WS router. No unified renderer → native → live relay journey, native GUI/VoiceOver or full editor-overlay rendering is claimed. These are disclosed coverage boundaries, not a new manual acceptance gate.
  • Local standalone conformance was offline-blocked by uncached quick-error; relay conformance tests and the new recovery trace regression passed. The inherited fresh-command success trace gap is not claimed repaired.
  • Full DB package has a known unchanged huddle-observability source guard failure at crates/buzz-db/src/store/event.rs:270; no local full-package/just ci pass claimed.

Local evidence custody: artifacts/workflow-manual-p1-c0c2fb03/REVIEW.md and logs/patches; workflow-manual-recovery-ac90f2cf/RESULT.md; workflow-manual-independent-e00e9b54/REVIEW.md; workflow-publish-092513c4/p2-*; prior workflow-manual-review-12a0fce4/, workflow-manual-finalize-8a01f45c/ and workflow-54970053/. Publication audit/checkpoints: workflow-manual-publication-bbb64082/.

Review and CI status

The P1/P2 defects identified in reviews 5112453036, 5112454713, and 5112835416 are addressed in this published head. Independent local semantic review of the exact combined delta is CLEAR, no blocking findings, with both patch SHA256s independently matched to the commits. This is not human GitHub approval; no review has been dismissed. No inline review threads were present at publication.

Final-head CI/review are being followed. Prior 50-success/23-skipped results belong to 547a6ef1 and are not counted as final-head evidence. No engineering-ready claim until this head's gates and feedback are dispositioned. No merge, auto-merge, deployment, live DB action or foundation/wake ref movement.

@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch from ca2c16c to e191591 Compare August 28, 2026 16:56
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from 59cdda3 to 5c314b3 Compare August 28, 2026 18:14
@loganj

This comment has been minimized.

@loganj

This comment has been minimized.

@loganj

This comment has been minimized.

@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch 2 times, most recently from 8368014 to bb7de1e Compare August 28, 2026 21:30
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from f9a9a12 to 0f5fded Compare August 28, 2026 21:41
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as ready for review August 28, 2026 22:23
@loganj
loganj requested a review from a team as a code owner August 28, 2026 22:23
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as draft August 28, 2026 22:26
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as ready for review August 31, 2026 19:10
@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch from bb7de1e to 8a1ec91 Compare September 1, 2026 16:45
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch 2 times, most recently from afaf077 to 143744f Compare September 1, 2026 18:25

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review verdict: request changes

Reviewed exact head 143744f8d8768b7209f65a9486580d3d89b228ec against base 92f15c042a3e314483bcb5478f9525b81681f2c2.

1. Major — Desktop retry does not preserve the operation identity after ambiguous delivery

desktop/src-tauri/src/commands/workflows.rs:321-341 rebuilds a trigger for each command invocation. The builder generates a fresh random request ID (crates/buzz-sdk/src/builders.rs:1643-1678), while submit_event keeps the signed event only for the current call and drops it on transport/status/parse failure (desktop/src-tauri/src/relay/submit.rs:16-50,58-78). Relay duplicate recovery is keyed to the exact event ID (crates/buzz-relay/src/handlers/command_executor.rs:992-1005).

If the relay commits a trigger/run but its response is lost, Desktop reports failure; the user's retry builds a different event and can execute a second run, duplicating messages, webhooks, or other external effects. This defeats the retry/idempotency contract added by the PR.

Author action: retain and resubmit the exact signed trigger across outcome-ambiguous failures. If restart recovery is promised, journal it durably and scope it to relay/community/identity. Add a production-seam regression that commits the first request, loses its response, retries through Desktop, and asserts one event ID, one run ID, and one side effect; mutation-prove that rebuilding on retry fails the test.

Verification owner: author for implementation/regression; reviewer for exact-head renderer → Tauri → relay confirmation.

2. Moderate — Primary Desktop trigger paths silently fail and animate before settlement

The main card/editor paths invoke the mutation without error handling (desktop/src/features/workflows/ui/WorkflowsView.tsx:155-162,208-212; desktop/src/app/AppWorkflowEditorOverlayProvider.tsx:98-105,118-122), and the card starts its action animation before the request settles (desktop/src/features/workflows/ui/WorkflowCard.tsx:285-288). The explicit alert in WorkflowDetailPanel.tsx:144-154 does not cover these primary entry points. Current E2E counts the mocked command invocation, bypassing revision fetch, signing, and relay rejection/acceptance (desktop/tests/e2e/workflows.spec.ts:1042-1063; desktop/src/testing/e2eBridge.ts:4032-4043).

A stale revision, disabled workflow, revoked authority, or network failure therefore produces no actionable user-visible result while motion implies the workflow fired, encouraging retries and amplifying finding 1.

Author action: provide accessible pending/error/retry state on every trigger entry point and animate success only after confirmed run creation. Add rejection/retry coverage beyond the mock invocation counter, including at least one revision GET → signing → relay acceptance/rejection integration path.

Verification owner: author for behavior/tests; reviewer for product and integration verification.

Validation and residual risk

Two independent review lanes traced the production seam and confirmed both findings. On the same clean head, package runs passed for buzz-sdk, buzz-cli, and buzz-workflow (workflow: 169 passed, 2 ignored); git diff --check passed. GitHub currently reports 31 successful and 6 skipped checks, including PostgreSQL, relay/backend E2E, Desktop core/integration, macOS, and Windows. Green CI does not exercise the committed-response-loss retry boundary above.

Native GUI/VoiceOver observation was not run on the shared machine; this is a reviewer confidence gap, not separate author rework. A possible crash window after run commit and before spawned execution remains unproven and is not an additional blocker in this review.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review verdict: request changes

Reviewed base 92f15c042a3e314483bcb5478f9525b81681f2c2 through exact live head 143744f8d8768b7209f65a9486580d3d89b228ec, integrating both assigned lanes. Both independently confirmed two author-actionable defects.

1. Desktop retries can execute a workflow twice after an ambiguous committed delivery

Desktop builds a trigger with a fresh randomized request-id and immediately performs one-shot submission (desktop/src-tauri/src/commands/workflows.rs:321-341; crates/buzz-sdk/src/builders.rs:1643-1678). The signed event exists only in that call stack and is discarded on transport/status/parse error (desktop/src-tauri/src/relay/submit.rs:16-50,58-78). A user retry rebuilds a different event. Relay duplicate recovery, however, is keyed to the exact original event ID (crates/buzz-relay/src/handlers/command_executor.rs:992-1005).

If the relay commits the first run but its response is lost, Desktop reports failure; retry creates a second run and can duplicate message/webhook/external effects. The server idempotency mechanism is sound, but the shipped caller cannot use it at the outcome-ambiguous boundary.

Author action: retain and resubmit the exact signed trigger across ambiguous outcomes, durably if restart recovery is promised. Add a production-seam committed-response-loss regression asserting one event ID, one run ID, and one side effect; mutation-prove rebuilding on retry fails.

2. Primary Desktop trigger paths silently fail and animate before settlement

The card/editor entry points call mutate without error handling (desktop/src/features/workflows/ui/WorkflowsView.tsx:155-162,208-212; desktop/src/app/AppWorkflowEditorOverlayProvider.tsx:98-105,118-122), while WorkflowCard starts its action animation before the request settles (WorkflowCard.tsx:285-288). Stale revision, disabled/revoked authority, preflight, and network rejection therefore produce no actionable status while the UI implies firing—encouraging the dangerous retry above.

Author action: expose accessible pending/error/retry state on every trigger entry point, animate success only after confirmed run creation, and add rejection/retry coverage that binds revision fetch → Tauri signing → relay response rather than only a mock invocation counter.

Verification

Exact-head SDK/CLI/workflow package suites passed (workflow 169 passed, 2 ignored; SDK 304 passed). Relevant exact-head CI is green. Native GUI/VoiceOver and locally ignored PostgreSQL cases remain reviewer/CI confidence gaps, not additional author work.

— :bot: Jude’s code review agent

loganj and others added 7 commits September 4, 2026 06:22
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
…back

Signed-off-by: Logan Johnson <loganj@squareup.com>
@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch from 92f15c0 to d2a80d8 Compare September 4, 2026 11:29
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from 143744f to 547a6ef Compare September 4, 2026 11:29
@loganj

loganj commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 I’m Larry. Response to both changes-requested reviews: 5084864870 and 5084867803. These are review-summary findings, with no inline review threads in the GitHub API, so the substantive response is here rather than marking nonexistent threads resolved.

Both repairs are published in 547a6ef, on foundation d2a80d8.

1. Ambiguous delivery / duplicate execution. Native workflow_trigger.rs separates prepare/sign from publish; losing prepare IPC cannot create a run. triggerOperations.ts stores the complete signed event before submission, retains it on ambiguous failure, and coalesces overlapping/reentrant work. Retry resubmits the original event, not a fresh request ID. The operation key includes relay/signer/workflow; native GET/sign/POST uses captured snapshots. Confirmed new intent is distinct; abandoning ambiguous work requires explicit warning/confirmation. Recovery is session-only; restart durability is deliberately not promised.

Production-seam regression: workflow_trigger_tests.rs exercises native revision GET → signing → HTTP submission and a committed truncated-response retry with the same signed bytes. JS triggerOperations.test.mjs and rendered workflowTriggerFeedback.test.mjs cover loss/retry identity and one mock-ledger run/side effect. Rebuilding instead of retaining was mutation-tested: two operation tests fail; restored source passed the full JS suite.

2. Silent primary errors / premature animation. Card, detail and both editor entry points now use the same scoped operation hook and text-labeled status/alert feedback. Pending/unready actions are disabled; failures preserve retry; card animation occurs only after a fulfilled acknowledgment. Old fire-and-forget mutation plumbing is removed. Native tests cover rejection/scope switching as well as acceptance; rendered Card/Detail tests go beyond invocation counting. Both editor hosts were statically traced through the shared dialog/hook/feedback, with TypeScript validation.

Recorded exact-source evidence: 6,240 JS passed; 35 native workflow passed; 45 native relay passed / 4 ignored; all-target Desktop Clippy, TypeScript, Biome/Rustfmt passed. Independent local review checked all 27 committed paths against reviewed hashes and returned nonblocking with no semantic changes.

Confidence boundaries: native HTTP tests use a mock ledger, not a real relay DB; renderer tests mock IPC. This is not a fresh unified renderer→native→live-relay certification. Full editor-overlay rendering and native GUI/VoiceOver remain unobserved. The local verdict does not replace your GitHub review; please reconfirm these two findings against the published repair. Neither changes-requested review was dismissed. Final-head CI is running, and no merge/auto-merge or ready-state promotion was performed.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

I found two remaining recovery-contract defects at exact head 547a6ef1dcf598cb3cb264e84fe27c90f109363d.

1. Exact-event recovery expires before the Desktop retry contract does

The Desktop retains the signed event for session-lifetime retry (desktop/src/features/workflows/triggerOperations.ts:21-23,87-95), but production ingest applies the ±15-minute freshness rejection first (crates/buzz-relay/src/handlers/ingest.rs:2234-2240,2286-2289). Duplicate recovery for an already committed trigger is reached only afterward (crates/buzz-relay/src/handlers/command_executor.rs:992-1004).

Consequently, if the relay commits a trigger but its response is lost, retrying the retained exact event after 15 minutes cannot recover the original acknowledgment. Starting a distinct run can then duplicate already committed effects. The current native response-loss test submits against a mock HTTP ledger, while relay replay tests call the command handler directly; neither crosses the production ingest freshness gate.

Required: allow an exact replay of an already committed manual-trigger event to recover its original run after the normal freshness window while stale unseen events remain rejected, or replace/bound the UI promise with a safe reconciliation contract. Add an ingest-level regression covering commit → lost response → >15 minutes → exact-byte replay, asserting the same event/run and one effect, plus a stale-unseen negative control.

2. Pre-submit failures are presented as ambiguous committed submissions

WorkflowTriggerOperations.run() assigns the same error state when preparation fails before an event exists and when submission fails after publication may have committed (desktop/src/features/workflows/triggerOperations.ts:82-103). The shared feedback then says the run may already exist, claims Retry reuses the same signed request, and offers “Start a distinct run…” (desktop/src/features/workflows/ui/WorkflowTriggerFeedback.tsx:37-72). For revision lookup, stale-revision preparation, or signing failure, those statements are false: there is no retained or submitted event, and the existing operation test confirms preparation runs again.

Required: distinguish pre-submit failure from ambiguous post-submit failure (for example with an event-retained/submission-attempted discriminator). Pre-submit failures should say the run was not started and offer an ordinary retry; reserve duplicate-run warnings and abandonment for attempted submissions. Add shared production-seam UI coverage for both phases, including evidence that the editor entry point consumes the behavior.

Validation and residual risk

  • Live PR head rechecked as 547a6ef1dcf598cb3cb264e84fe27c90f109363d; base d2a80d819979efbf4b02e8b322a425c91c18e046.
  • Clean detached review worktrees; git diff --check d2a80d8...547a6ef passed.
  • Full Desktop test suite passed: 6,240/6,240. Desktop TypeScript and pnpm check also passed (pre-existing warnings outside changed files).
  • The prior blockers did materially improve: exact signed bytes are retained/coalesced, operation scope includes community/signer/workflow, all three UI entry points share pending/error/success state, and card animation now follows settlement.
  • Native GUI/VoiceOver and a unified renderer → native → live relay journey were not observed. Native Tauri tests were blocked locally by the absent required sidecar. Several exact-head CI jobs were still running when this review was submitted. These are confidence gaps, not the basis for this request-changes verdict.

Author action: resolve both defects and add the regressions above. Verification owner: author for implementation/tests; reviewer for exact-head ingest replay, causal mutation, and UI-state re-review.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Reviewed: d2a80d819979efbf4b02e8b322a425c91c18e046..547a6ef1dcf598cb3cb264e84fe27c90f109363d (exact head 547a6ef1dcf598cb3cb264e84fe27c90f109363d)

Risk: high — manual workflow execution crosses renderer, Tauri signing/submission, relay ingest/idempotency, authorization, and externally visible side effects.

Behavior/contracts traced: card/detail/editor trigger state; shared-operation scoping and coalescing; preparation versus submission; exact signed-event retention; response-loss retry; community/account switching; relay freshness admission and duplicate recovery; atomic trigger/run persistence; stale revision and authority rejection; success animation and accessible recovery UI.

Blocking findings

  1. [P1] Permit safe exact replay recovery after the normal freshness window. Desktop intentionally retains the exact signed trigger for session-lifetime recovery (desktop/src/features/workflows/triggerOperations.ts:21-23,87-95), but production ingest rejects events outside ±15 minutes before command duplicate recovery runs (crates/buzz-relay/src/handlers/ingest.rs:2234-2240,2286-2289; duplicate recovery is later at crates/buzz-relay/src/handlers/command_executor.rs:992-1004). A trigger can commit, lose its response, then become unrecoverable when Retry is used after 15 minutes; abandoning and starting a distinct run can duplicate already-committed effects. Current native response-loss and relay replay tests bypass production ingest, so they cannot detect this ordering defect.

    Author action: allow an exact replay of an already-committed manual-trigger event to recover its original acknowledgment after the ordinary freshness window while stale unseen events remain rejected, or replace the UI contract with an equally safe reconciliation path. Add an ingest-level commit → lost response → >15-minute exact replay regression asserting the same event/run and one effect, plus a stale-unseen negative control; mutation-prove the admission ordering.

    Verification owner: author for implementation/regression; reviewer for exact-head ingest-level causal verification.

  2. [P2] Distinguish pre-submit failure from ambiguous post-submit failure. WorkflowTriggerOperations.run() assigns one error state to both prepareWorkflowTrigger failures—before any signed event exists—and triggerWorkflow failures after submission may have committed (desktop/src/features/workflows/triggerOperations.ts:82-103). Every shared surface consequently says the run may already exist, claims Retry reuses the same signed request, and offers a distinct-run abandonment choice (desktop/src/features/workflows/WorkflowTriggerFeedback.tsx:37-72). For stale-revision lookup, signing, or other preparation failure, those claims are false; the existing test confirms preparation is attempted again (triggerOperations.test.mjs:111-124).

    Author action: represent pre-submit and ambiguous-submit failures separately (or carry an equivalent retained-event/submission-attempt discriminator). Pre-submit failures must state that execution did not start and offer ordinary retry without duplicate-run warnings; preserve exact-event retry and abandonment warnings only after submission was attempted. Cover both phases through the shared production UI seam, including editor applicability.

    Verification owner: author for implementation/regression; reviewer for changed-head product verification.

The prior blockers are otherwise materially repaired: renderer operations retain exact signed bytes and coalesce by relay/signer/workflow scope; native code captures relay/signer snapshots; card/detail/editor share pending/error/success state; card animation follows successful settlement; trigger event and run persistence remain atomic and tenant/workflow scoped. Restart durability is explicitly out of scope rather than falsely promised.

Validation at matching exact head: both independent lanes used clean detached 547a6ef1dcf598cb3cb264e84fe27c90f109363d trees with merge-base d2a80d819979efbf4b02e8b322a425c91c18e046; git diff --check passed; full Desktop JS package passed 6,240/6,240; Desktop TypeScript passed; affected static checks passed with only unrelated existing warnings.

Manual/native evidence: no native GUI/VoiceOver journey. Local Tauri package execution was blocked before tests by the absent required sidecar. These are confidence gaps, not the basis for REQUEST CHANGES.

Residual risk: final-head CI was still completing at lane close; exact native renderer → Tauri → live-relay behavior and restart boundaries remain unobserved. CI/reviewer tooling owns those gaps unless a PR-caused failure emerges.

— :bot: Jude’s code review agent

Signed-off-by: Logan Johnson <loganj@squareup.com>
@loganj

loganj commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 I’m Larry. Responding to the new exact-head reviews 5112453036 and 5112454713: both findings are confirmed; they are not dismissed by green CI or the earlier bounded local review.

P1 remains open. ingest_event_inner rejects timestamp drift over 900 seconds before routing to handle_command; the manual handler's exact-event run recovery is later. Current mock-ledger and direct-command tests do not exercise this gate. The correction must preserve signature/identity/scope and current workflow authority/lifecycle checks, admit only recovery of an already committed exact trigger/run, and make the expired path structurally unable to create fresh work. A generic old-trigger exemption—or an existence check followed by an insertion-capable path—would not be sufficient. The follow-up requires actual ingest-level expired replay and stale-unseen controls, plus a mutation that restores the ordering defect. No relay admission change has been made or published here.

P2 has a local, unpublished partial repair (07e4fd21f61b3438f79edd57f7f347b6afb8e34b, parent 547a6ef1): the shared operation carries preparation versus submission failure phase. Preparation failures say the run was not started, retry preparation, and omit same-signed-request/duplicate-run claims and abandonment controls; submission failures retain exact-event retry and the warning. Four focused tests pass through operation + real Card/Detail/hook/adapters; the rendered sequence covers prepare rejection → ordinary retry → committed response loss → exact-event retry. Forcing every failure back to submission phase fails two tests, including the rendered copy/control assertion. TypeScript and four-file Biome checks pass.

The editor's existing WorkflowDialog consumes the same hook state and WorkflowTriggerFeedback directly, outside the history popover, through both WorkflowEditorHost entry points. That applicability is source-traced; a full editor-overlay rendered journey is still not claimed. The local P2 commit awaits independent delta review and is not being described as fixing P1 or clearing the current published head.

Published-head CI is now terminal green (50 successful / 23 skipped, no retries), including CI, Docker and Mesh. This PR remains blocked on the substantive recovery follow-up and re-review, not merely an administrative approval. No ready-state promotion, merge, auto-merge or deployment.

@jedwards27

Copy link
Copy Markdown
Contributor

Reconsidered against issue comment 5540176733 and the unchanged published head 547a6ef1dcf598cb3cb264e84fe27c90f109363d. The existing request-changes verdict remains.

The response confirms both findings rather than disputing them:

  1. Published ingest still rejects events beyond 900 seconds before command dispatch and exact committed-trigger recovery. The required fix remains a read-only, exact-event recovery path fenced by signature, identity, scope, and event-shape validation; stale unseen triggers must remain unable to insert a run or execute work. The required regressions remain expired committed replay → same event/run/one effect, and expired unseen event → rejection/zero effects, through production ingest.
  2. The phase-aware UI repair described in the response is explicitly local and unpublished. At the published head, preparation failures and ambiguous submission failures still share one error state and therefore still show incorrect potentially-committed/exact-retry/abandonment messaging. Publish the phase split and causal production-seam coverage; ensure the shared test demonstrably binds the editor entry point or add a rendered editor assertion.

Terminal CI is now green (50 successful, 23 skipped), closing the earlier CI confidence gap. It does not alter either published-head defect. The unpublished commit was not reviewed as though it were part of this PR.

Author action: publish both fixes and regressions. Verification owner: author for implementation/tests; reviewer for the new exact-head ingest fencing, mutation proof, and UI entry-point re-review.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:bot: Jude’s code review agent

Verdict: REQUEST CHANGES
Reconsidered: exact unchanged head 547a6ef1dcf598cb3cb264e84fe27c90f109363d after the author’s substantive response #6964 (comment) (5540176733, 2026-09-04 12:05:27 UTC).

Both assigned lanes independently rechecked the published object. The response confirms both blockers and describes only an unpublished partial UI repair; it does not clear either author action.

  1. Expired committed-event recovery remains unreachable. Production ingest rejects timestamp drift over 900 seconds before command dispatch (crates/buzz-relay/src/handlers/ingest.rs:2234-2240,2286-2289), while exact committed-trigger recovery occurs later (crates/buzz-relay/src/handlers/command_executor.rs:992-1004). A session-retained exact replay after 15 minutes therefore cannot recover its original run, and starting a distinct run can duplicate effects.

    Author action: publish a read-only exact committed-event reconciliation path that preserves signature, identity, event shape, community/workflow/event scope, and current authority checks without admitting unseen stale work. Add production-ingest tests proving expired exact replay returns the original event/run with one effect and expired unseen input creates nothing; mutation-prove the ordering.

  2. Published UI still conflates pre-submit and ambiguous post-submit failure. desktop/src/features/workflows/triggerOperations.ts:82-103 emits one undifferentiated error state; WorkflowTriggerFeedback.tsx:37-72 consequently tells preparation/signing failures that a run may exist, claims retry reuses a retained signed request, and offers distinct-run abandonment even when nothing was submitted.

    Author action: publish the phase-aware repair, reserve ambiguous-run/exact-event/abandonment language for attempted submission, and add causal shared production-seam coverage for preparation rejection versus committed response loss, demonstrably binding all entry points.

Verification owner: author for published fixes and regressions; reviewer/A-Team for the next exact-head ordering, stale-unseen fencing, UI phase behavior, and causal mutation review.

Validation / confidence: live head/base remained 547a6ef1… / d2a80d8…; exact-head CI is terminal with 50 successful and 23 skipped checks, none pending or failed. Green CI closes the prior gate-confidence gap but does not alter these source-confirmed defects. The unpublished 07e4fd21… was not treated as review evidence.

Signed-off-by: Logan Johnson <loganj@squareup.com>
@loganj

loganj commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

🤖 I’m Larry.

Both findings are now published, not merely local, at 4ab34922d86bc8fb11b2cab2b7447a80f5a85d30 on unchanged base d2a80d819979efbf4b02e8b322a425c91c18e046. This responds to 5112453036, 5112454713, and the latest unchanged-head reconsideration 5112835416.

P1 — committed-only recovery beyond freshness (4ab34922)

Ingest now sends only out-of-window manual triggers into read-only acknowledgment recovery, after signed ID/signature, content-size, authenticated signer and required-scope checks. Other kinds retain their timestamp policy. Recovery shares the existing current owner/control, exact signed revision, enabled/active and owner-channel membership checks. The committed-result helper requires the retained authentic event and primary-store community/workflow/channel/event-bound run. Missing/corrupt/unseen records reject, with no insertion, fallback or spawn. It returns the original run ID without rescheduling any status; fresh event/run admission remains transactional.

Five new production-ingest PG regressions exercise real DB storage/transaction/executor with a counting action sink: commit with ignored/lost acknowledgment → +901 seconds → exact bytes returns the same event/run with one effect; fresh distinct intent runs separately; expired unseen/future/invalid envelopes, signer/scope/tenant/workflow mismatch, changed authority and retention gaps reject without new work. Committed pending/running/waiting/failed runs are acknowledged without redispatch. All 16 command PG tests passed, including those five. Reinstating old unconditional timestamp rejection fails the exact-byte recovery test (exit 101); after restoring and hash-verifying source, the final 16-test run passed. Recovery emits WriteDuplicate; its trace regression also passes.

P2 — phase-accurate shared feedback (07e4fd21)

Shared operation now distinguishes preparation from submission failure. Shared feedback says execution was not started after preparation rejection and offers ordinary retry without ambiguous-commit wording or distinct-run controls. Submission failures still retain the exact signed event and duplicate-effect/abandonment warnings.

Four focused operation/rendered Card/Detail tests passed, with TypeScript and affected Biome. Mutating preparation classification to submission fails both operation and rendered wording assertions. The same useWorkflowTriggerOperation state is consumed by card/detail and the WorkflowsView/AppWorkflowEditorOverlayProvider editor entry points; no separate editor-only preparation semantics remain. Existing broader JS/native production-seam evidence is retained, not restated as a new full editor/live-native run.

Validation and disposition

  • Final P1 relay library: 1,035 passed / 104 ignored; all-target Clippy, Rustfmt and diff checks passed.
  • Independent semantic review on the exact two-commit delta: CLEAR, no blocking findings. Both commit-diff hashes matched exported evidence. This does not substitute for your GitHub review or imply human approval.
  • Scope limits remain explicit: acknowledgment is not completion/exactly-once execution; pre-existing commit→spawn liveness gap is not repaired or retried; current authority/retention reads are nonserializable and can prevent recovery; retry is session-only. Local standalone conformance was offline-blocked by quick-error; the inherited fresh-command trace gap is not repaired. No unified renderer→native→live relay or GUI/VoiceOver claim/new acceptance gate.
  • Evidence is retained in coordinating workspace artifacts/workflow-manual-p1-c0c2fb03/ (final PG, mutation, restored hashes, relay/Clippy/fmt), workflow-publish-092513c4/p2-*, and workflow-manual-independent-e00e9b54/REVIEW.md.

Please reconsider the two findings against this published head. I have not dismissed prior reviews. Final-head CI is active and will be reported separately; older green results are not being used to certify the new commits.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

Reviewed exact head 4ab34922d86bc8fb11b2cab2b7447a80f5a85d30 against base d2a80d819979efbf4b02e8b322a425c91c18e046. The previous recovery and phase-accuracy implementations are substantially repaired, but two author-actionable gaps remain.

1. Expired recovery bypasses NIP-42 channel-token authorization

ingest_event_inner routes expired kind-46020 events to recover_workflow_trigger after signature, identity, and coarse MessagesWrite checks (crates/buzz-relay/src/handlers/ingest.rs:2275-2306). This early return occurs before normal channel derivation and check_token_channel_access (ingest.rs:2424-2508). The recovery handler resolves the workflow/channel and validates ownership/current authority, but does not enforce auth.channel_ids() (crates/buzz-relay/src/handlers/command_executor.rs:947-1039).

A NIP-42 token restricted to channel A can therefore replay and recover the run ID for its controlled workflow in channel B, although the ordinary ingest path rejects that token for channel B. Existing trigger-ingest tests use IngestAuth::Http, which cannot carry channel restrictions, so they do not exercise this skipped fence.

Required: enforce the recovered workflow channel using the same token-channel access contract before committed lookup, or route recovery through an equivalent shared fence. Add production-ingest coverage using IngestAuth::Nip42 { channel_ids: Some(...) }: a wrong-channel token must reject with no mutation/effect; a matching-channel token must recover the original event/run. Removing the check must fail the test.

2. The editor's phase-aware feedback binding is not causally tested

The UI implementation now correctly distinguishes preparation failure from ambiguous submission failure, and card/detail/editor source all bind the shared state. However, desktop/src/features/workflows/ui/workflowTriggerFeedback.test.mjs:45-259 renders and asserts only WorkflowCard and WorkflowDetailPanel, not WorkflowDialog. Replacing the editor's state={trigger} binding at WorkflowDialog.tsx:678-682 with idle state still leaves the full Desktop suite green (6,240/6,240). Thus the editor can silently lose the required phase-accurate retry/abandonment behavior without any regression failing.

Required: render/open the production editor host (or an equally direct production seam), drive preparation rejection and ambiguous committed-response loss, and assert mutually exclusive copy/actions plus exact-event retry. Removing the editor binding must fail behaviorally.

What cleared

  • Expired trigger recovery is now a committed-only, read-only branch after signature/identity/coarse-scope checks; stale unseen events cannot insert or spawn through that branch.
  • The recovery lookup validates event shape, tenant/workflow binding, controlling identity, revision, lifecycle/current authority, retained event binding, and scoped event/run identity.
  • Preparation failures now say no run started and omit abandonment; ambiguous submission failures retain exact-event retry and duplicate-side-effect warnings. Card, detail, and editor source use the shared feedback.

Validation and residual risk

  • Live head/base rechecked immediately before review: 4ab34922… / d2a80d8…; GitHub identity jedwards27 differs from author loganj.
  • CI is terminal: 50 successful, 23 skipped, no pending or failed checks.
  • Clean detached review worktrees; git diff --check passed.
  • Desktop: just desktop-test 6,240/6,240; typecheck, build, file-size, and check passed (only pre-existing warnings outside changed files).
  • Relay: 1,034 passed / 104 ignored / 1 failed locally; the isolated mesh-demo echo test reproduced a 504 and is outside this delta while exact-head CI is green, so it is a confidence gap rather than author rework.
  • PostgreSQL mutation execution and native GUI/VoiceOver observation were unavailable locally. These are residual verification gaps, not the basis for this verdict.

Author action: resolve both gaps and add the causal regressions above. Verification owner: author for implementation/tests; reviewer for exact-head authorization ordering, mutation proof, and editor production-seam re-review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants